package parser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import tables.Artist;

import DBside.JDBCConnection;
import DBside.Tools;


import entities.CD;
import entities.Track;


public class Parser {
		static String title="";
		static String ttitle="";
		static int cur_title_num=0;
		static boolean dtitle_bool=false;
		static boolean found_dtitle=false;
		/*
	public static void main(String[] args) throws FileNotFoundException
	{//check out april update file 560f8b06 in misc disk length is something L seconds check if it means something
		String path = "/media/3E5CD2685CD21B0B/workspace/database/3f0dc206";
		InputStream file = new FileInputStream(path);
		CD cd = parseCD(file);
		
	}
	*/
		
	/**
	 * 
	 * @param file - a file in the freeDB cd file format.
	 * @return	if successful -	return the a java-object CD corresponding to the input file.
	 * 			if fails -		returns null.
	 */
	public static CD parseCD(InputStream file){
		Token currToken = null;
		dtitle_bool=false;
		found_dtitle=false;
		// FileReader txtFile = null;
		CD cd = new CD();
		List<Track> cds_add_artist=new ArrayList<Track>();
		cur_title_num=0;
		title="";
		ttitle="";
	    try {
	        //txtFile = new FileReader(file);
	        Lexer scanner = new Lexer(file);
	        do {
	            currToken = scanner.next_token();
	 	       //System.out.println("here1");

	            if(!currToken.tokenType.equals("DTITLE")&&!dtitle_bool&&found_dtitle)
	            { 
	            	processTitle(title, cd);
	            	dtitle_bool=true;
	            }
	 	       //System.out.println("here2");

	            processToken(currToken, cd,cds_add_artist);
	            //System.out.println(currToken+": "+currToken.value);	        	
	        
	        } while (currToken.id != sym.EOF);
	        //System.out.println(cd);
		       //System.out.println("here3");

		    processTTitle(ttitle, cd,cds_add_artist);
		    for(Track t:cds_add_artist)
		    {
			     //  System.out.println("here4");

		    	t.getArtist().addArtist(cd.getAlbumArtist());
		    }
		    
		    /*
		    for(Track t:cd.getTracks())
		    {
		    	t.addArtist(cd.getAlbumArtist());
		    }
		    */
	        return cd;
	    }
	    catch(ArrayIndexOutOfBoundsException e){return null;}
	    catch(NullPointerException e){return null;}
	    catch (LexicalError e) {System.out.println(e.toString());}
	    catch (Exception e) {throw new RuntimeException("IO Error (brutal exit)"+e.toString());}
	    finally{
	    	/*try {
				txtFile.close();
			} catch (IOException e) {
				e.printStackTrace();
			}*/
	    }
	    return null;
	}
	

	private static void processToken(Token token, CD cd,List<Track> cds) {
		if(token.tokenType.equals("DISC_LEN"))
			cd.setDiscLength(token.value);
		else if(token.tokenType.equals("DISCID"))
			cd.addId(token.value);
		else if(token.tokenType.equals("DTITLE"))
		{	
			found_dtitle=true;
			//	System.out.println("XXX1");
			title+=token.value.trim();
			//System.out.println("XXX2");
			//processTitle(token.value, cd);
		}
		else if(token.tokenType.equals("DYEAR"))
			cd.addYear(Integer.parseInt(token.value));
		else if(token.tokenType.equals("DGENRE"))
			cd.addGenreName(token.value.trim());
		else if(token.tokenType.equals("TTITLE"))
		{
			//System.out.println("XXX3");
			ttitle+=token.value.trim();
			//System.out.println("XXX4");
		//	processTTitle(token.value, cd);
		}
		else if(token.tokenType.equals("TTITLE_NUM"))
		{
			if(cur_title_num!=Integer.parseInt(token.value))
			{
				
				processTTitle(ttitle, cd,cds);
				ttitle="";
			}
			cur_title_num=Integer.parseInt(token.value);
			//title+=token.value;
		//	processTTitle(token.value, cd);
		}
		//else if(token.tokenType.equals("REVISION"))
	//		throw new NullPointerException();
	}

	private static void processTTitle(String tTitle, CD cd,List<Track> cds) {
		String[] titleParts = tTitle.split("/");
		if(titleParts.length == 1){	//no artist specified - use disc's artist
			if(titleParts[0].trim().length()>=255)
			{
				//System.out.println("MERD1");
				throw new NullPointerException();
			}
			Track track  = new Track(cd.getAlbumArtist().getName(), titleParts[0].trim());
			//cds.add(track);
			cd.addTrack(track);
			//TODO shai added this part for the test
			/*
			 * it seems like we:
			 *  1. add blank artists (instead of unknown)
			 *  2. add all except one time the artist with his name and one time the artist with blank name
			 *  
			 *   example: Sam & Dave ->
			 *   		you will find on his disk an empty name with all of his songs except for one
			 *   		and one instace with his name correctly...
			 *   
			 *   you can check it on updateByFolder wite file name 000c9c13 
			 */
			//System.out.println("test: " + track.getArtist().getName());
			//TODO: end of shai test
		}
		else if(titleParts.length >= 2){	//TODO: titleParts[1] - Track's title, titleParts[0] - Artist(/s)
			String a="";
			if(titleParts[titleParts.length-1].trim().length()>=255)
			{
				//System.out.println("MERD1");
				throw new NullPointerException();
			}
			
			for(int i=1;i<titleParts.length-2;i++)
				a+=titleParts[i]+" & ";
			a+=	titleParts[titleParts.length-2];
			
			if(a.trim().length()>=255)
			{
				//System.out.println("MERD1");
				throw new NullPointerException();
			}
			Track track = new Track(a.trim(), titleParts[titleParts.length-1].trim());
			cd.addTrack(track);
		}
		else{	//should get here - against syntax
		System.out.println("processTTitle: CRAP!: "+tTitle);
		}
		
	}

	private static void processTitle(String dTitle, CD cd) {
		String[] titleParts = dTitle.split("/");
		if(titleParts.length == 1){ 	//no artist specified -- should not get here - against syntax
			if(dTitle.trim().length()>=255)
			{
				//System.out.println("MERD1");
				throw new NullPointerException();
			}
			cd.addAlbumName(dTitle.trim());
			cd.addArtistToAlbum(new Artist(-1, "Unknown"));
		}
		else if(titleParts.length>= 2) {	//titleParts[1] - Disc's title, titleParts[0] - Artist(/s)
			//cd.setTitle(titleParts[1].trim());
		//	cd.setArtist(titleParts[0].trim());
			int k;
			String a="";
			for(k=0;k<titleParts.length-2;k++)
			{
				a+=titleParts[k].trim()+" & ";
			}
			a+=titleParts[k].trim();
			
			
			if(titleParts[k+1].trim().length()>=255)
			{
				//System.out.println("MERD1");
				throw new NullPointerException();
			}
			
			if(a.trim().length()>=255)
			{
				//System.out.println("MERD1");
				throw new NullPointerException();
			}
			
			cd.addAlbumName(titleParts[k+1].trim());
			cd.addArtistToAlbum(new Artist(-1,a.trim())); 
		}
		else{	//should not get here - against syntax
			System.out.println("processTitle: CRAP! "+cd.getId());
		}
	}

}
